import { useConfig } from "@/hooks/useConfig";
import { useThree } from "@react-three/fiber";
import { useControls } from "leva";
import { useEffect } from "react";
import { ShaderChunk } from "three";

/**
 * 色调映射设置
 *
 * 该设置用于调整场景的色调映射，以实现不同的色彩风格和视觉效果。
 * - "No"：不应用色调映射。
 * - "Linear"：线性色调映射。
 * - "AgX"：AgX 色调映射，适用于模拟胶卷效果。
 * - "ACESFilmic"：ACES Filmic 色调映射，用于高动态范围图像。
 * - "Reinhard"：Reinhard 色调映射，适用于保留高光细节。
 * - "Cineon"：Cineon 色调映射，适用于模拟电影胶卷效果。
 * - "Custom"：自定义色调映射：曝光调整、暗部修正、亮部压缩、去饱和化。
 *
 * 注意：该设置会受到后处理效果的覆盖，例如 Bloom 或其他光照效果可能会影响最终的视觉结果。
 *
 * 曝光设置
 *
 * 默认值为 0.85，适合大多数场景的基本曝光需求。
 * 注意：过高的曝光可能会导致图像过曝，而过低的曝光可能会使图像显得过暗。
 */
export default function ToneSet() {
  const { tone } = useConfig();
  const [{ 色调映射, 曝光 }, set] = useControls(
    "色调设置",
    () => ({
      曝光: { value: 0.85, min: 0, max: 4 },
      色调映射: {
        value: "ACESFilmic",
        options: Object.values(ToneMap).filter((v) => typeof v === "string"),
      },
    }),
    { collapsed: true, order: 1 }
  );

  const gl = useThree((state) => state.gl);

  useEffect(() => {
    set({
      色调映射: tone.toneMapping,
      曝光: tone.exposure,
    });
  }, [tone]);

  useEffect(() => {
    const prevFrag = ShaderChunk.tonemapping_pars_fragment;
    const prevTonemapping = gl.toneMapping;
    const prevTonemappingExp = gl.toneMappingExposure;
    gl.toneMapping = ToneMap[色调映射 as keyof typeof ToneMap];
    gl.toneMappingExposure = 曝光;
    return () => {
      // 卸载组件时恢复默认设置
      gl.toneMapping = prevTonemapping;
      gl.toneMappingExposure = prevTonemappingExp;
      ShaderChunk.tonemapping_pars_fragment = prevFrag;
    };
  }, [色调映射, 曝光]);

  return null;
}
enum ToneMap {
  No,
  Linear,
  Reinhard,
  Cineon,
  ACESFilmic,
  Custom,
  AgX,
}
